#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef struct {
    /* data */
    unsigned char  head_type;
    unsigned short len;
    unsigned short file_L;
    unsigned short file_H;
    unsigned char  data[0];
}__attribute__ ((__packed__)) DATA;

struct ClientData {
    int   PORT;
    int   client_fd;
    char *AddressIP;
    struct sockaddr_in server;
} cli_data;

void close_fd(int signum)
{
    close(cli_data.client_fd);
    exit(signum);
}

int main(int argc,char **argv){
    if (argc < 4) {
        printf("args is not enough!!!\n" \
               "this command is {./file_client [ip] [port] [path/file]}\n"
        );
        return -1;
    }
    signal(SIGINT, close_fd);
    cli_data.client_fd = socket(PF_INET, SOCK_STREAM, 0);
    if ( cli_data.client_fd == -1) {
        perror("socket error");
        exit(-1);
    }

    memset(&cli_data.server, '\0', sizeof(cli_data.server));
    cli_data.AddressIP = argv[1];
    cli_data.PORT      = atoi(argv[2]);

    cli_data.server.sin_family      = AF_INET;
    cli_data.server.sin_addr.s_addr = inet_addr(cli_data.AddressIP);
    cli_data.server.sin_port        = htons(cli_data.PORT);

    if (connect(cli_data.client_fd, (struct sockaddr*)(&cli_data.server), sizeof(struct sockaddr)) < 0) {
        perror("connect error");
        exit(-1);     
    }
    int file_fd = open(argv[argc - 1], O_RDWR);
    if (file_fd < 0) {
        perror("open");
        kill(getpid(), SIGINT);
    }
    
    int file_len = lseek(file_fd, 0, SEEK_END);
    if (file_len < 0) {
        perror("lseek");
        kill(getpid(), SIGINT);
    }
    printf("file size : %d\n", file_len);
    lseek(file_fd, 0, SEEK_SET);
    int offset = 0, send_len = 0 , times = 0;
    while (1) {
        unsigned char buf[1024] = {'\0'};
        if (file_len - offset > 1024) send_len = read(file_fd, buf, 1024);
        else                         send_len = read(file_fd, buf, file_len - offset);
        offset += send_len;
        // #ifdef DEBUG
        // #endif

        DATA *sendmsg = (DATA *)malloc(sizeof(DATA) + send_len + 1);
        sendmsg->head_type      = 0x7B;
        sendmsg->len            = send_len + sizeof(DATA) + 1;
        sendmsg->file_L         = file_len & 0x0000ffff;
        sendmsg->file_H         = file_len >> 16;
        sendmsg->data[send_len] = 0x7a;
        memcpy(sendmsg->data, buf, send_len);
        #ifdef DEBUG
        for (int i = 0; i < sendmsg->len - sizeof(DATA) - 1; i++) {
            printf("%c ", sendmsg->data[i]);
            fflush(stdin);
        }
        printf("\n");
        #endif
        usleep(5); //加延时丢包率少
        unsigned char *send_buf = (char *)sendmsg;
        // getchar();
        printf("==%x %x %x %x %x %x %x==\n", send_buf[0], send_buf[1], send_buf[2], send_buf[3], send_buf[4], send_buf[5], send_buf[6]);
        int size = send(cli_data.client_fd, sendmsg, sendmsg->len, 0);
        // times++;
        // printf("offset : %d free : %d send_len:%d size:%d times:%d\n", offset, file_len - offset, send_len, size, times);
        free(sendmsg);
        if (!(file_len - offset)) {
            printf("transpot file sucessfully\n");
            close(file_fd);
            kill(getpid(), SIGINT);
        }
    }
    
    return 0;
}